/*
 ============================================================================
 Name        : AssemblerCommon.h
 Author      : Sherry Krikszer
 Version     : 1.0
 Copyright   : --
 Description :  in C, ANSI-style
 ============================================================================
 */

#ifndef ASSEMBLERCOMMON_H_
#define ASSEMBLERCOMMON_H_

#include "Common.h"

/* ----------------------------------------------------------------------------
 *	Constants Definition
 * ----------------------------------------------------------------------------*/

#define MAX_PROGRAM_LINE_COUNT		MAX_LINE_COUNT
#define MAX_SYMBOL_NAME_LENGTH 		31
#define MAX_COMMAND_NAME_LENGTH 	4
#define MAX_DIRECTIVE_NAME_LENGTH 	6
#define MAX_OPERANDS_COUNT 			5

#define MAX_OPERAND_STRING_LENGTH 	20
#define MAX_OPERANDS_PER_COMMAND	2

#define STARTING_MEMORY_ADDRESS 	100

#define UNKNOWN_ADDRESS				-1

#define DATA_DIRECTIVE 		"data"
#define STRING_DIRECTIVE 	"string"
#define ENTRY_DIRECTIVE 	"entry"
#define EXTERN_DIRECTIVE 	"extern"

#define ABSOLUTE				'a'
#define RELOCATABLE				'r'
#define EXTERNAL				'e'
#define EMPTY_LINK_OPTION		LINE_END

#define EXTERN_PARAM_SYMBOL_LOCATION 0
#define EXPECTED_EXTERN_PARAM_COUNT  1

#define ENTRY_PARAM_SYMBOL_LOCATION 0
#define EXPECTED_ENTRY_PARAM_COUNT	1

/* ----------------------------------------------------------------------------
 *	Constants Definition End
 * ----------------------------------------------------------------------------*/

/* ----------------------------------------------------------------------------
 *	Type Definition
 * ----------------------------------------------------------------------------*/

typedef enum {COMMAND, DIRECTIVE} StatementType;

typedef union
{
	char commandName[MAX_COMMAND_NAME_LENGTH];
	char directive[MAX_DIRECTIVE_NAME_LENGTH];
}Statement;

typedef enum {CODE_WORD, DATA_WORD} WordType;

typedef union
{
	/* TODO : note that a data param can be negative*/
	/*unsigned*/ int DataWord 							: 16;
	struct
	{
		unsigned int destinationRegister 			: 3;
		unsigned int destinationAddressingMethod 	: 3;
		unsigned int sourceRegister 				: 3;
		unsigned int sourceAddressingMethod 		: 3;
		unsigned int opcode 						: 4;
	}CodeWord;
}Word;

typedef struct
{
	WordType wordType;
	Word wordEncoding;
	unsigned int offset;
}MemoryWord;

typedef struct
{
	MemoryWord machineCode;
	unsigned char linkInformation;
}InstructionMemoryWord;

typedef struct
{
	InstructionMemoryWord codeSegment[MAX_PROGRAM_LINE_COUNT];
	int IC;
	int codeBaseAddress;

	MemoryWord 			  dataSegment[MAX_PROGRAM_LINE_COUNT];
	int DC;
	int dataBaseAddress;

}Memory;

typedef enum
{
	CODE, DATA, EXTERN, ENTRY
}SymbolType;

typedef struct
{
	int offset;
	char symbolName[MAX_SYMBOL_NAME_LENGTH];
	SymbolType symbolType;
}Symbol;

typedef struct
{
	Symbol symbols[MAX_PROGRAM_LINE_COUNT];
	int symbolBaseAdress;
	int SC;
}SymbolTable;

typedef struct
{
	char* 			registerName;
	unsigned int 	registerAddress : 3;
}Register;

typedef enum
{
	UNDEFINED				= -1,
	IMMEDIATE_ADDRESSING 	= 0,
	DIRECT_ADDRESSING 		= 1,
	INDEX_ADDRESSING 		= 2,
	DOUBLE_INDEX_ADDRESSING = 3,
	REGISTER_ADDRESSING 	= 4
}AddressingMethod;

typedef struct
{
	int operandBaseWord 	: 16;
	char operandBaseSymbol[MAX_OPERAND_STRING_LENGTH];
	char linkingOptionBaseWord;

	int operandExtendWord 	: 16;
	char operandExtendSymbol[MAX_OPERAND_STRING_LENGTH];
	char linkingOptionExtendWord;
	Register registerOperand;

	AddressingMethod operandAdressingMethod;
}Operand;

typedef enum
{
	MOV, CMP, ADD, SUB, NOT, CLR, LEA, INC,
	DEC, JMP, BNE, RED, PRN, JSR, RTS, HLT,
	INVALID
}CommandType;

typedef struct
{
	Operand operands[MAX_OPERANDS_PER_COMMAND];
	int operandCount;
	int sizeInWords;
	CommandType commandType;
}CommandOperands;

typedef struct
{
	char paramValues[MAX_OPERANDS_COUNT][MAX_OPERAND_STRING_LENGTH];
	int paramCounter;
}Params;

typedef struct
{
	char symbol[MAX_SYMBOL_NAME_LENGTH];
	StatementType statementType;
	Statement statement;
	Params params;
}CommandLineTokens;

typedef struct
{
	FileLine* 			originalFileLine;
	Boolean 			shouldBeHandled;
	CommandLineTokens* 	commandTokens;
	CommandOperands* 	commadParsedOperands;
	Boolean				parseErrorOccured;
	ErrorMessage 		errorMessage;
}ParsedProgramLine;

typedef struct
{
	ParsedProgramLine lines[MAX_PROGRAM_LINE_COUNT];
	int lineCounter;
}ProgramLines;

/* ----------------------------------------------------------------------------
 *	Type Definition End
 * ----------------------------------------------------------------------------*/

#endif /* ASSEMBLERCOMMON_H_ */
